/*
 * Created on February 21, 2007
 * 
 * Copyright (c) Patrick Armstrong 2002-2007. All Rights Reserved
 */
package org.dime.util;

/**
 * Tuple // TODO Add type summary
 * 
 * @author Owner
 */
public class Tuple<T, S>
{
    private T head;
    private S tail;

    /**
     * 
     */
    public Tuple()
    {
        this(null, null);
    }

    /**
     * 
     * @param head
     * @param tail
     */
    public Tuple(T head, S tail)
    {
        this.head = head;
        this.tail = tail;
    }

    /**
     * 
     * @return
     */
    public T getHead()
    {
        return head;
    }

    /**
     * 
     * @param head
     */
    public void setHead(T head)
    {
        this.head = head;
    }

    /**
     * 
     * @return
     */
    public S getTail()
    {
        return tail;
    }

    /**
     * 
     * @param tail
     */
    public void setTail(S tail)
    {
        this.tail = tail;
    }

    /**
     * @param obj
     * 
     * @return
     */
    @Override
    public boolean equals(Object obj)
    {
        if (obj instanceof Tuple)
        {
            try
            {
                // Because the JVM does not store information about generic
                // types it is impossible to know that the cast from Object to
                // Tuple<T, S> will succeed so suppress the warning to keep the
                // compiler from worrying.
                @SuppressWarnings("unchecked")
                Tuple<T, S> other = (Tuple<T, S>) obj;
                return getHead().equals(other.getHead())
                        && getTail().equals(other.getTail());
            }
            catch (ClassCastException cce)
            {}
        }
        return false;
    }

    /**
     * @return
     */
    @Override
    public int hashCode()
    {
        return getHead().hashCode() + getTail().hashCode();
    }

    @Override
    public String toString()
    {
        return "<" + getHead().toString() + ", " + getTail().toString() + ">";
    }

}
